package com.guoxue.action.front;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.guoxue.consts.CUser;
import com.guoxue.consts.SCUser;
import com.guoxue.domain.FollowsVo;
import com.guoxue.domain.UserVo;
import com.guoxue.service.IFollowsService;
import com.guoxue.service.IUserService;
import com.guoxue.util.OSSUtil;
import com.guoxue.util.codeSwitch.zt;

/**
 * 用户好友处理接口，主要包括： 1.getFriends获取第三方好友在自己平台的好友列表 2.searchUser查询好友列表中的某个好友信息
 * 3.getFriendsInfo获取好友列表的每个人的个人信息用于展示（聊天窗体中使用）
 * 
 * @author kanghb
 *
 */
@Controller
@RequestMapping("Util")
public class FriendsAction extends BaseAction {
	static {
		zt.tb.optimize(); // 在本机内存中,缓存用户的"简单"数据(需要定时清理,以及过期更新机制)
		zt.ts.optimize();
		// 在对IFollowsService中获取列表的方法底层,进行分页重构(仅从数据库中加载一部分数据!)
		// (排序分页时,依据的排序规则,是表中的id?或需要增加Long型时间列)
		// 同时,需要重构受影响的客户端接口。
		zt.ts.function(); // 将所有的oss动态url(通过oss.getUrl调用),改为固定的静态url。客户端定期获取一个整bucket的"只读"权限token。

		zt.ts.function(); // 封装获取一个UserVo的简单信息,并填写为json对象的调用。
		zt.ta.function(); // 好友数量,黑名单数量,都有上限。(暂定好友200~400,黑名单100~200)

		zt.ta.optimize(); // 成员变量oss和bucket待删除(图片url改为静态后)

		zt.ta.function(); // 将FriendsAction的"@RequestMapping"改到User下,与FollowsAction合并!
	}

	@Resource
	private OSSUtil oss;
	private static final String bucket = "bykj-gx-oss-bucket1";

	@Resource
	private IUserService userService;
	@Resource
	private IFollowsService followsService;

	/**
	 * 聊天界面使用，获取昵称等信息
	 * 
	 * @param req
	 * @param resp
	 * @param uids
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/getFriendsInfo")
	public JSON dep_getFriendsInfo(HttpServletRequest req, HttpServletResponse resp, String uids) {
		zt.ts.function(); // 待作废,用getUsersInfo_byIds接口代替!

		if (isEmpty(uids)) {
			return Message(ERROR, "uids为空", null);
		}
		String[] userIds = uids.split(",");
		JSONArray array = new JSONArray();
		for (String uid : userIds) {
			int id = Integer.parseInt(uid);
			UserVo user = userService.getUserByKey(id);
			if (user != null) {
				JSONObject obj = new JSONObject();
				obj.put("uid", id);
				obj.put("name", user.getNickName());
				obj.put("sex", user.getSex());
				obj.put("urlImg", isEmpty(user.getImgUrl()) ? null
						: oss.getUrl(bucket, user.getImgUrl(), new Date(new Date().getTime() + 3600 * 1000 * 24)));
				array.add(obj);
			}
		}
		return Message(SUCCESS, "获取用户信息成功", array.size() > 0 ? array : null);
	}

	/**
	 * 根据客户端提交的用户账号表,获取这批用户的简单信息,以及每个用户是否是当前用户的好友等状态
	 * 
	 * @param req
	 * @param resp
	 * @param accountsList
	 *            用户账号列表,每个账号之间,用英文逗号","隔开。
	 * @param accountsType
	 *            用户账号类型,目前接受:1:手机号,2:QQ号,3:微信号,4:新浪微博。(详见CUser.ACCOUNTS_TYPE_系列常数)
	 * @return
	 */
	@RequestMapping("/getUsersInfo_byAccounts")
	@ResponseBody
	public JSON A2_getUsersInfo_byAccounts(HttpServletRequest req, HttpServletResponse resp, String accountsList,
			Integer accountsType) {
		final int uid = SCUser.getUidFromReq(req);

		if (isEmpty(accountsList)) {
			return Message(ERROR, "请求账号列表为空", null);
		}
		if (accountsType == null) {
			return Message(ERROR, "账号类型为空", null);
		}
		switch (accountsType) {
		case CUser.ACCOUNTS_TYPE_TEL:
		case CUser.ACCOUNTS_TYPE_QQ:
		case CUser.ACCOUNTS_TYPE_WeiXin:
		case CUser.ACCOUNTS_TYPE_SinaWeibo:
			break;
		default:
			return Message(ERROR, "账号类型错误", null);
		}

		final JSONArray jsonArray;
		String[] accountsArray = accountsList.split(",");
		UserVo userVo;
		JSONObject json_user;

		// accountsArray的长度检查,不能为空,也不能超出"单页数量上限":
		if (accountsArray == null || accountsArray.length <= 0) {
			return Message(ERROR, "请求账号列表为空", null);
		}
		if (accountsArray.length > CUser.USERS_COUNT_PER_PAGE_NORMAL) {
			zt.ts.function(); // 协调客户端,设置单页请求上限
			return Message(ERROR, "请求账号列表超出了数量上限", null);
		}

		jsonArray = new JSONArray();
		for (String account : accountsArray) {
			zt.tc.optimize(); // 对account字符串的合法性检查,例如不能包含空格等特殊字符,防止造成有危害的sql语句!
			userVo = userService.getUser(account, accountsType);
			if (userVo == null) {
				continue;
			}
			// 根据userVo,创建对应的回复数据对象:
			json_user = this.userSimpleInfo_toJson(userVo, null);
			zt.tc.optimize(); // 统一json格式
			json_user.put("userImg", json_user.get("headUrl"));
			json_user.remove("signature");

			// 判断是否同时被我所关注:
			zt.tb.optimize(); // 考虑到"我关注的人"(即我的好友)数量有限,是否应该获取总是获取"我的好友列表",在该列表中查找判断?
			FollowsVo follow = followsService.getFriendById(userVo.getId(), uid, 0);
			if (follow == null) {
				json_user.put("followed", false);
			} else {
				json_user.put("followed", true);
			}
			jsonArray.add(json_user);
		}
		return Message(SUCCESS, "获取好友列表成功", jsonArray);
	}

	/**
	 * 一次性获取多个指定用户的简单信息(例如在聊天界面中显示用户列表)
	 * 
	 * @param req
	 * @param resp
	 * @param uids
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/getUsersInfo_byIds")
	public JSON A2_getUsersInfo_byIds(HttpServletRequest req, HttpServletResponse resp, String uids) {
		// final int uid = SCUser.getUidFromReq(req);
		int uid_userSimple;
		JSONObject json_user;
		final JSONArray jsonArray;

		if (isEmpty(uids)) {
			return Message(ERROR, "请求用户id列表为空", null);
		}
		final String[] uidsArray = uids.split(",");
		// accountsArray的长度检查,不能为空,也不能超出"单页数量上限":
		if (uidsArray == null || uidsArray.length <= 0) {
			return Message(ERROR, "请求账号列表为空", null);
		}
		if (uidsArray.length > CUser.USERS_COUNT_PER_PAGE_NORMAL) {
			zt.ts.function(); // 协调客户端,设置单页请求上限
			return Message(ERROR, "请求账号列表超出了数量上限", null);
		}

		jsonArray = new JSONArray();
		for (String uidStr : uidsArray) {
			uid_userSimple = Integer.parseInt(uidStr);
			UserVo userVo = userService.getUserSimpleInfo(uid_userSimple);
			if (userVo == null) {
				continue; // 该id的用户不存在
			}
			// 根据userVo,创建对应的回复数据对象:
			json_user = this.userSimpleInfo_toJson(userVo, null);
			jsonArray.add(json_user);
		}

		return Message(SUCCESS, "获取用户信息成功", jsonArray.size() > 0 ? jsonArray : null);
	}

	/**
	 * 获取关注关系列表
	 * 
	 * @param req
	 * @param resp
	 * @param type
	 *            获取类型:1.获取关注我的人列表;2.获取我关注的人列表;
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/getAssociatedUsers")
	public JSON A2_getAssociatedUsers(HttpServletRequest req, HttpServletResponse resp, Integer type) {
		final int uid = SCUser.getUidFromReq(req);
		final List<FollowsVo> followsVoList;
		final JSONArray jsonArray;
		JSONObject json;
		UserVo userVo;
		int uid_userSimple;

		// 参数基本检查:
		if (type == null || type < 1 || type > 2) {
			return Message(ERROR, "获取类型错误", null);
		}

		// 获取列表:
		zt.tb.function(); // 将用户的好友(和黑名单)列表数据缓存在内存中,不需要查询数据库()
		if (type == 1) { // 获取关注我的人列表
			followsVoList = followsService.getFriendsList(uid);
		} else { // (type == 2) 获取我关注的人(我的好友)列表
			followsVoList = followsService.getFollowedList(uid);
		}
		if (followsVoList.size() <= 0) {
			return Message(SUCCESS, "获取好友列表成功", null);
		}

		// 遍历列表:
		jsonArray = new JSONArray();
		for (FollowsVo f : followsVoList) {
			if (type == 1) { // 获取关注我的人列表
				uid_userSimple = f.getFollower();
				// userVo = userService.getUserByKey(f.getFollower());
			} else { // (type == 2) 获取我关注的人(我的好友)列表
				uid_userSimple = f.getFollowed();
				// userVo = userService.getUserByKey(f.getFollowed());
			}
			userVo = userService.getUserSimpleInfo(uid_userSimple);
			if (userVo == null) {
				zt.tb.question(); // 关联的用户不存在,删除与其相关的关系记录?(有点危险!)(不应出现,添加warning打印)
				continue; // 关联的用户不存在
			}
			// json = new JSONObject();
			json = this.userSimpleInfo_toJson(userVo, null);

			if (type == 1) { // 获取关注我的人列表
				// 判断是否同时被我所关注:
				zt.tb.optimize(); // 考虑到"我关注的人"(即我的好友)数量有限,是否应该获取总是获取"我的好友列表",在该列表中查找判断?
				FollowsVo fo = followsService.getFriendById(uid_userSimple, uid, 0);
				if (fo == null) {
					json.put("follow", false);
				} else {
					json.put("follow", true);
				}
			}
		}
		return Message(SUCCESS, "获取好友列表成功", jsonArray);
	}

	/**
	 * 获取黑名单列表
	 * 
	 * @param req
	 * @param resp
	 * @return
	 */
	@RequestMapping("/getBlackUsers")
	@ResponseBody
	public JSON A2_getBlackUsers(HttpServletRequest req, HttpServletResponse resp) {
		final int uid_this = SCUser.getUidFromReq(req);
		List<FollowsVo> followsVoList;
		JSONArray jsonArray;
		JSONObject json_user;

		// 参数基本检查:

		// 获取列表:
		zt.tb.function(); // 将用户的好友(和黑名单)列表数据缓存在内存中,不需要查询数据库()
		followsVoList = followsService.getBlackList(uid_this);
		if (followsVoList.size() <= 0) {
			return Message(SUCCESS, "获取黑名单成功", null);
		}

		followsVoList = followsService.getBlackList(uid_this);
		jsonArray = new JSONArray();
		if (followsVoList.size() > 0) {
			for (FollowsVo f : followsVoList) {
				UserVo userVo = userService.getUserSimpleInfo(f.getFollowed());
				if (userVo == null) {
					continue; // 该id的用户不存在
				}
				// 根据userVo,创建对应的回复数据对象:
				json_user = this.userSimpleInfo_toJson(userVo, null);
				jsonArray.add(json_user);
			}
		}
		return Message(SUCCESS, "获取黑名单成功", jsonArray);
	}

	/**
	 * 获取第三方好友在自己平台的好友列表
	 * 
	 * @param req
	 * @param resp
	 * @param userId
	 *            第三方平台返回用户id
	 * @param type
	 *            类型 1：sina。 2：qq 3:手机号
	 * @param uid
	 *            自己平台该用户id
	 * @return
	 */
	@RequestMapping("/getOtherFriends")
	@ResponseBody
	public JSON dep_getFriends(HttpServletRequest req, HttpServletResponse resp, String userId, Integer type,
			Integer uid) {
		zt.ts.function(); // 待作废,用getUsersInfo_byAccounts接口代替!
		if (isEmpty(userId)) {
			return Message(ERROR, "第三方账号uid为空", null);
		}
		if (type == null) {
			return Message(ERROR, "账号类型为空", null);
		}
		if (uid == null) {
			return Message(ERROR, "当前用户id未提交", null);
		}
		JSONArray array = new JSONArray();
		String[] userIds = userId.split(",");
		for (String userid : userIds) {
			UserVo users = null;
			// T:是否存在其他类型?
			if (type == 1) {
				users = userService.getUserBySina(userid);
			}
			if (type == 2) {
				users = userService.getUserByQq(userid);
			}
			if (type == 3) {
				users = userService.getUserByTel(userid);
			}
			if (users != null) {
				JSONObject obj = new JSONObject();
				obj.put("nickName", users.getNickName());
				obj.put("userImg", isEmpty(users.getImgUrl()) ? null
						: oss.getUrl(bucket, users.getImgUrl(), new Date(new Date().getTime() + 3600 * 1000 * 24)));
				obj.put("userId", userid);
				obj.put("uid", users.getId());
				obj.put("sex", users.getSex());
				FollowsVo follow = followsService.getFriendById(users.getId(), uid, 0);
				if (follow == null) {
					obj.put("followed", false);
				} else {
					obj.put("followed", true);
				}
				array.add(obj);
			}
		}
		return Message(SUCCESS, "获取好友列表成功", array);
	}

	/**
	 * 好友内查询
	 * 
	 * @param req
	 * @param resp
	 * @param name
	 *            被查询者昵称
	 * @param type
	 *            1: 我关注的查询、2：粉丝查询，3：黑名单查询
	 * @return
	 */
	@RequestMapping("searchUser")
	@ResponseBody
	public JSON A2_searchAssociatedUsers_nameLike(HttpServletRequest req, HttpServletResponse resp, String name,
			Integer type) {
		final int uid = SCUser.getUidFromReq(req);
		// TODO:
		zt.ts.function(); // 接口重命名为searchAssociatedUsers_nameLike,并通知客户端去掉了uid参数

		// 参数基本检查:
		if (type == null || type <= 0 || type > 3) {
			return Message(ERROR, "未知type类型", null);
		}
		if (name == null || name.length() <= 0) {
			return Message(ERROR, "未提交昵称", null);
		}
		if (name.length() <= 1) {
			char c = name.charAt(0);
			if (c >= 0 && c < 256) {
				return Message(ERROR, "昵称过短", null);
			}
		}
		zt.tc.optimize(); // 对name字符串的合法性检查,例如不能包含空格等特殊字符,防止造成有危害的sql语句!

		///////////////////////////////////////////////////////////////
		zt.ts.function(); // 从这里开始,下面的部分待重构:
		zt.ts.function(); // 根据不同的type,编写相应的数据库关联查询,优化查询效率
		List<UserVo> users = null;
		if (type != 3) {
			int c = 0;
			if (type == 2) {
				c = 3;
			}
			users = userService.getByName(uid, c, name);
		} else {
			users = userService.geFensByUid(uid, name);
		}

		JSONArray array = new JSONArray();
		if (users != null) {
			for (Iterator it = users.iterator(); it.hasNext();) {
				Object[] ob = (Object[]) it.next();
				JSONObject obj = new JSONObject();
				obj.put("nickName", ob[0].toString());
				obj.put("sex", ob[4]);
				obj.put("signature", isEmpty(ob[3].toString()) ? null : ob[3].toString());
				obj.put("headUrl", isEmpty(ob[2].toString()) ? null
						: oss.getUrl(bucket, ob[2].toString(), new Date(new Date().getTime() + 3600 * 1000 * 12)));
				obj.put("uid", ob[1]);
				array.add(obj);
			}
		}
		return Message(SUCCESS, "成功搜所到好友", array.size() > 0 ? array : null);
	}

	private JSONObject userSimpleInfo_toJson(final UserVo userVo, JSONObject json) {
		zt.ta.function(); // 去掉对url的动态获取

		if (json == null) {
			json = new JSONObject();
		}
		json.put("uid", userVo.getId());
		json.put("headUrl", isEmpty(userVo.getImgUrl()) ? null
				: oss.getUrl(bucket, userVo.getImgUrl(), new Date(new Date().getTime() + 3600 * 1000 * 24)));
		json.put("sex", userVo.getSex());
		json.put("nickName", userVo.getNickName());
		json.put("signature", userVo.getPersonSignature());
		return json;
	}

	/**
	 * 获取关注列表
	 * 
	 * @param req
	 * @param resp
	 * @param userId
	 *            用户id
	 * @param type
	 *            获取数据类型 1：获取关注我的人列表、2：获取我关注的人列表
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/getFriendsList")
	public JSON dep_getFriendsList(HttpServletRequest req, HttpServletResponse resp, Integer userId, Integer type) {
		zt.ts.function(); // 待作废,用"getAssociatedUsers"接口代替
		if (userId == null) {
			return Message(ERROR, "未提交用户id", null);
		}
		if (type == null) {
			return Message(ERROR, "未指定关注类型", null);
		}
		List<FollowsVo> fvl = null;
		JSONArray array = new JSONArray();
		if (type == 1) {
			fvl = followsService.getFriendsList(userId);
		}
		if (type == 2) {
			fvl = followsService.getFollowedList(userId);
		}
		if (fvl.size() > 0) {
			for (FollowsVo f : fvl) {
				JSONObject obj = new JSONObject();
				UserVo user = null;
				if (type == 1) {
					user = userService.getUserByKey(f.getFollower());
					FollowsVo fo = followsService.getFriendById(f.getFollower(), userId, 0);
					if (fo == null) {
						obj.put("follow", false);
					} else {
						obj.put("follow", true);
					}
				}
				if (type == 2) {
					user = userService.getUserByKey(f.getFollowed());
				}
				if (user != null) {
					obj.put("uid", user.getId());
					obj.put("headUrl", isEmpty(user.getImgUrl()) ? null
							: oss.getUrl(bucket, user.getImgUrl(), new Date(new Date().getTime() + 3600 * 1000 * 24)));
					obj.put("sex", user.getSex());
					obj.put("nickName", user.getNickName());
					obj.put("signature", isEmpty(user.getPersonSignature()) ? null : user.getPersonSignature());
					array.add(obj);
				}
			}

		}
		return Message(SUCCESS, "获取好友列表成功", array.size() > 0 ? array : null);
	}
}
